<template>
	<view>
	  <view class="content" @touchstart="hideDrawer">
		<scroll-view
		  class="msg-list dialogue-box"
		  scroll-y="true"
		  :scroll-with-animation="scrollAnimation"
		  :scroll-top="scrollTop"
		  :scroll-into-view="scrollToView"
		  @scrolltoupper="loadHistory"
		  upper-threshold="50"
		  bindscrolltolower="true"
		>
		  <view class="dialogue-box-content">
			<view
			  class="row"
			  v-for="(row, index) in msgList"
			  :key="index"
			  :id="'msg' + row.msg.id"
			>
			  <!-- 用户消息 -->
			  <block v-if="row.type == 'user'">
				<!-- 自己发出的消息 -->
				<view class="my" v-if="row.msg.userinfo.uid == myuid">
				  <!-- 左-消息 -->
				  <view class="left">
					<!-- 文字消息 -->
					<view v-if="row.msg.type == 'text'" class="bubble">
					  <rich-text :nodes="row.msg.content.text"></rich-text>
					</view>
					<!-- 语言消息 -->
					<view
					  v-if="row.msg.type == 'voice'"
					  class="bubble voice"
					  @tap="playVoice(row.msg)"
					  :class="playMsgid == row.msg.id ? 'play' : ''"
					>
					  <view class="length">{{ row.msg.content.length }}</view>
					  <view class="icon my-voice"></view>
					</view>
					<!-- 图片消息 -->
					<view
					  v-if="row.msg.type == 'img'"
					  class="bubble img"
					  @tap="showPic(row.msg)"
					>
					  <image
						:src="row.msg.content.url"
						:style="{
						  width: row.msg.content.w + 'px',
						  height: row.msg.content.h + 'px',
						}"
					  ></image>
					</view>
				  </view>
				  <!-- 右-头像 -->
				  <view class="right">
					<image src="@/static/right-header.png"></image>
				  </view>
				  <view>{{ test }}</view>
				</view>
  
				<!-- 别人发出的消息 -->
				<view
				  v-if="row.msg.userinfo.uid != myuid"
				  style="
					display: flex;
					flex-direction: column;
					/* align-items: flex-end; */
				  "
				>
				  <view class="other">
					<!-- 左-头像 -->
					<view class="left">
					  <image src="@/static/left-header.png"></image>
					</view>
					<!-- 右-用户名称-时间-消息 -->
					<view class="right">
					  <!-- <view class="username">
					<view class="name">{{ row.msg.userinfo.username }}</view>
					<view class="time">{{ row.msg.time }}</view>
				  </view> -->
					  <!-- 文字消息 -->
					  <view v-if="row.msg.type == 'text'" class="bubble">
						<rich-text :nodes="row.msg.content.text"></rich-text>
					  </view>
					  <!-- 语音消息 -->
					  <view
						v-if="row.msg.type == 'voice'"
						class="bubble voice"
						@tap="playVoice(row.msg)"
						:class="playMsgid == row.msg.id ? 'play' : ''"
					  >
						<view class="icon other-voice"></view>
						<view class="length">{{ row.msg.content.length }}</view>
					  </view>
					  <!-- 图片消息 -->
					  <view
						v-if="row.msg.type == 'img'"
						class="bubble img"
						@tap="showPic(row.msg)"
					  >
						<image
						  :src="row.msg.content.url"
						  :style="{
							width: row.msg.content.w + 'px',
							height: row.msg.content.h + 'px',
						  }"
						></image>
					  </view>
					</view>
				  </view>
				  <view
					class="anawer-tips"
					v-show="index == msgList.length - 1 && appendContent && !ifStopSock"
					@click="stopSock"
					>停止回答</view
				  >
				</view>
			  </block>
			  <view v-if="index === 0" class="question-tips"
				><view>常见问题：</view>
				<view
				  v-for="(item, type) in questionList"
				  :key="type"
				  @click="questionBtn(item)"
				  >{{ type + 1 }}、{{ item }}</view
				>
			  </view>
			</view>
		  </view>
		</scroll-view>
	  </view>
	  <!-- 抽屉栏 -->
	  <!-- <view
		class="popup-layer"
		:class="popupLayerClass"
		@touchmove.stop.prevent="discard"
	  >
	  </view> -->
	  <!-- 底部输入栏 -->
	  <view
		class="input-box"
		:class="popupLayerClass"
		@touchmove.stop.prevent="discard"
	  >
		<!-- H5下不能录音，输入栏布局改动一下 -->
		<!-- #ifndef H5 -->
		<view class="voice">
		  <view
			class="icon"
			:class="isVoice ? 'jianpan' : 'yuyin'"
			@tap="switchVoice"
		  ></view>
		</view>
		<!-- #endif -->
		<!-- #ifdef H5 -->
		<view class="more" @tap="showMore">
		  <view class="icon add"></view>
		</view>
		<!-- #endif -->
		<view class="textbox">
		  <view
			class="voice-mode"
			:class="[isVoice ? '' : 'hidden', recording ? 'recording' : '']"
			@touchstart="voiceBegin"
			@touchmove.stop.prevent="voiceIng"
			@touchend="voiceEnd"
			@touchcancel="voiceCancel"
			>{{ voiceTis }}</view
		  >
		  <view class="text-mode" :class="isVoice ? 'hidden' : ''">
			<view class="box">
			  <textarea
				auto-height="true"
				v-model="textMsg"
				@focus="textareaFocus"
				:show-confirm-bar="false"
				:cursorSpacing="20"
			  />
			</view>
		  </view>
		</view>
		<view
		  :class="isVoice ? 'hidden' : ''"
		  @tap="sendText"
		  style="width: 80rpx,height:100%;"
		>
		  <image
			src="@/static/send-btn.png"
			style="
			  width: 50rpx;
			  height: 50rpx;
			  margin-top: 25rpx;
			  margin-left: 10rpx;
			  padding: 0rpx 30rpx 0rpx 5rpx;
			"
		  ></image>
		</view>
	  </view>
	  <!-- 录音UI效果 -->
	  <view class="record" :class="recording ? '' : 'hidden'">
		<view class="ing" :class="willStop ? 'hidden' : ''"
		  ><view class="icon luyin2"></view
		></view>
		<view class="cancel" :class="willStop ? '' : 'hidden'"
		  ><view class="icon chehui"></view
		></view>
		<view class="tis" :class="willStop ? 'change' : ''">{{ recordTis }}</view>
	  </view>
	</view>
  </template>
  <script>
  export default {
	data() {
	  return {
		//文字消息
		tempFilePath: "",
		textMsg: "",
		json: "",
		//消息列表
		isHistoryLoading: false,
		scrollAnimation: false,
		scrollTop: 0,
		scrollToView: "",
		msgList: [],
		msgImgList: [],
		myuid: 0,
  
		//录音相关参数
		// #ifndef H5
		//H5不能录音
		RECORDER: uni.getRecorderManager(),
		// #endif
		isVoice: false,
		voiceTis: "按住 说话",
		recordTis: "手指上滑 取消发送",
		recording: false,
		willStop: false,
		initPoint: { identifier: 0, Y: 0 },
		recordTimer: null,
		recordLength: 0,
  
		//播放语音相关参数
		AUDIO: uni.createInnerAudioContext(),
		playMsgid: null,
		VoiceTimer: null,
		// 抽屉参数
		popupLayerClass: "",
		// more参数
		hideMore: true,
		//表情定义
		hideEmoji: true,
  
		//表情图片图床名称 ，由于我上传的第三方图床名称会有改变，所以有此数据来做对应，您实际应用中应该不需要
  
		//红包相关参数
		windowsState: "",
		redenvelopeData: {
		  rid: null, //红包ID
		  from: null,
		  face: null,
		  blessing: null,
		  money: null,
		},
		appendContent: "",
		oldSendMsgIndex: 0,
		sSum: null,
		ifStopSock: false,
		questionList: [
		  "什么是医保电子凭证?",
		  "医保电子凭证如何修改密码?",
		  "如何办理异地就医?",
		  "什么是亲情账户?",
		  "新生儿如何参保?",
		],
	  };
	},
	onLoad(option) {
	  this.getMsgList();
	  //语音自然播放结束
	  this.AUDIO.onEnded((res) => {
		this.playMsgid = null;
	  });
	  // #ifndef H5
	  //录音开始事件
	  this.RECORDER.onStart((e) => {
		this.recordBegin(e);
	  });
	  //录音结束事件
	  this.RECORDER.onStop((e) => {
		this.recordEnd(e);
	  });
	  // #endif
	},
	onShow() {
	  if (uni.getStorageSync("userName")) {
		this.sSum = uni.getStorageSync("userName");
	  } else {
		(this.sSum = Math.floor(Math.random() * 100)),
		  uni.setStorageSync("userName", this.sSum);
	  }
	  console.log(this.sSum, "this.sSum");
	  uni.connectSocket({
		url: `wss://abc.gszczn.com:18587/terminal/lma/chat/${this.sSum}`,
	  });
	  uni.onSocketOpen(function (res) {
		console.log("WebSocket连接已打开！");
	  });
	  // let content = "测试234123";
	  // setInterval(() => {
	  //   this.leftMsg((content += "aaa"), "text", this.oldSendMsgIndex == 0);
	  // }, 5000);
  
	  this.json = "";
	  uni.onSocketMessage((res) => {
		this.appendContent += res.data;
		this.leftMsg(this.appendContent, "text", this.oldSendMsgIndex == 0);
	  });
  
	  uni.onSocketError(function (res) {
		console.log("WebSocket连接打开失败，请检查！");
		uni.connectSocket({
		  url: `wss://abc.gszczn.com:18587/terminal/lma/chat/${this.sSum}`,
		});
	  });
	  this.scrollTop = 9999999;
  
	  //模板借由本地缓存实现发红包效果，实际应用中请不要使用此方法。
	  //
	  uni.getStorage({
		key: "redEnvelopeData",
		success: (res) => {
		  let lastid = this.msgList[this.msgList.length - 1].msg.id;
		  lastid++;
		  let row = {
			type: "user",
			msg: {
			  id: lastid,
			  type: "redEnvelope",
			  time: "",
			  userinfo: {
				uid: 0,
				username: "大黑哥",
				face: "/static/img/face.jpg",
			  },
			  content: {
				blessing: res.data.blessing,
				rid: Math.floor(Math.random() * 1000 + 1),
				isReceived: false,
			  },
			},
		  };
		  this.screenMsg(row);
		  uni.removeStorage({ key: "redEnvelopeData" });
		},
	  });
	},
	methods: {
	  // 接受消息(筛选处理)
	  screenMsg(msg) {
		//从长连接处转发给这个方法，进行筛选处理
		if (msg.type == "system") {
		  // 系统消息
		  switch (msg.msg.type) {
			case "text":
			  this.addSystemTextMsg(msg);
			  break;
			case "redEnvelope":
			  this.addSystemRedEnvelopeMsg(msg);
			  break;
		  }
		} else if (msg.type == "user") {
		  // 用户消息
		  switch (msg.msg.type) {
			case "text":
			  this.addTextMsg(msg);
			  break;
			case "voice":
			  this.addVoiceMsg(msg);
			  break;
			case "img":
			  this.addImgMsg(msg);
			  break;
			case "redEnvelope":
			  this.addRedEnvelopeMsg(msg);
			  break;
		  }
		}
		this.$nextTick(function () {
		  // 滚动到底
		  this.scrollToView = "msg" + msg.msg.id;
		});
	  },
	  questionBtn(type) {
		this.textMsg = type;
		this.sendText();
	  },
	  stopSock() {
		this.oldSendMsgIndex = 0;
		this.appendContent = "";
		this.ifStopSock = true;
		uni.closeSocket();
		uni.connectSocket({
		  url: `wss://abc.gszczn.com:18587/terminal/lma/chat/${this.sSum}`,
		});
		uni.onSocketOpen((res) => {
		  // uni.sendSocketMessage({ data: this.textMsg });
		});
	  },
	  //触发滑动到顶部(加载历史信息记录)
	  loadHistory(e) {
		if (this.isHistoryLoading) {
		  return;
		}
		this.isHistoryLoading = true; //参数作为进入请求标识，防止重复请求
		this.scrollAnimation = false; //关闭滑动动画
		let Viewid = this.msgList[0].msg.id; //记住第一个信息ID
		//本地模拟请求历史记录效果
		setTimeout(() => {
		  // 消息列表
		  let list = [];
		  // 获取消息中的图片,并处理显示尺寸
		  for (let i = 0; i < list.length; i++) {
			if (list[i].type == "user" && list[i].msg.type == "img") {
			  list[i].msg.content = this.setPicSize(list[i].msg.content);
			  this.msgImgList.unshift(list[i].msg.content.url);
			}
			list[i].msg.id = Math.floor(Math.random() * 1000 + 1);
			this.msgList.unshift(list[i]);
		  }
  
		  //这段代码很重要，不然每次加载历史数据都会跳到顶部
		  this.$nextTick(function () {
			this.scrollToView = "msg" + Viewid; //跳转上次的第一行信息位置
			this.$nextTick(function () {
			  this.scrollAnimation = true; //恢复滚动动画
			});
		  });
		  this.isHistoryLoading = false;
		}, 1000);
	  },
	  // 加载初始页面消息
	  getMsgList() {
		// 消息列表
		let list = [
		  {
			type: "user",
			msg: {
			  id: 2,
			  type: "text",
			  time: "",
			  userinfo: {
				uid: 1,
				username: "",
				face: "/static/img/im/face/face_2.jpg",
			  },
			  content: {
				text: "亲爱的用户您好，如果您有跟医保相关的疑问，欢迎向我提问，很高兴为您服务！",
			  },
			},
		  },
		];
  
		this.msgList = list;
		// 滚动到底部
		this.$nextTick(function () {
		  //进入页面滚动到底部
		  this.scrollTop = 9999;
		  this.$nextTick(function () {
			this.scrollAnimation = true;
		  });
		});
	  },
	  //处理图片尺寸，如果不处理宽高，新进入页面加载图片时候会闪
	  setPicSize(content) {
		// 让图片最长边等于设置的最大长度，短边等比例缩小，图片控件真实改变，区别于aspectFit方式。
		let maxW = uni.upx2px(350); //350是定义消息图片最大宽度
		let maxH = uni.upx2px(350); //350是定义消息图片最大高度
		if (content.w > maxW || content.h > maxH) {
		  let scale = content.w / content.h;
		  content.w = scale > 1 ? maxW : maxH * scale;
		  content.h = scale > 1 ? maxW / scale : maxH;
		}
		return content;
	  },
  
	  //更多功能(点击+弹出)
	  showMore() {
		this.isVoice = false;
		this.hideEmoji = true;
		if (this.hideMore) {
		  this.hideMore = false;
		  this.openDrawer();
		} else {
		  this.hideDrawer();
		}
	  },
	  // 打开抽屉
	  openDrawer() {
		this.popupLayerClass = "showLayer";
	  },
	  // 隐藏抽屉
	  hideDrawer() {
		this.popupLayerClass = "";
		setTimeout(() => {
		  this.hideMore = true;
		  this.hideEmoji = true;
		}, 150);
	  },
  
	  //获取焦点，如果不是选表情ing,则关闭抽屉
	  textareaFocus() {
		if (this.popupLayerClass == "showLayer" && this.hideMore == false) {
		  this.hideDrawer();
		}
	  },
	  // 发送文字消息
	  sendText() {
		this.hideDrawer(); //隐藏抽屉
		if (!this.textMsg) {
		  return;
		}
		this.ifStopSock = false;
  
		uni.sendSocketMessage({ data: this.textMsg });
  
		this.sendMsg(this.textMsg, "text");
		this.loading = true;
  
		this.leftMsg("正在思考中...", "text", true);
		this.textMsg = ""; //清空输入框
	  },
  
	  // 发送消息
	  sendMsg(content, type) {
		//消息发出后所做操作
		let lastid = this.msgList[this.msgList.length - 1].msg.id;
		lastid++;
		let msg = {
		  type: "user",
		  msg: {
			id: lastid,
			time: "",
			type: type,
			userinfo: {
			  uid: 0,
			  username: "大黑哥",
			},
			content: type == "text" ? { text: content } : { url: content.url },
		  },
		};
		// 发送消息
		this.screenMsg(msg);
		// 定时器模拟对方回复,三秒
	  },
  
	  leftMsg(content, type, append) {
		let lastid = this.msgList[this.msgList.length - 1].msg.id;
		if (append) {
		  lastid++;
		}
		let msg = {
		  type: "user",
		  msg: {
			id: lastid,
			time: "",
			type: type,
			userinfo: {
			  uid: 1,
			  username: "",
			},
			content: type == "text" ? { text: content } : { url: content.url },
		  },
		};
		// 本地模拟发送消息
		this.screenMsg(msg);
	  },
  
	  // 添加文字消息到列表
	  addTextMsg(msg) {
		// let msgItem = this.msgList[this.msgList.length - 1].msg;
		if (msg.msg.userinfo.uid == "0") {
		  this.msgList.push(msg);
		} else {
		  const findIndex = this.msgList.findIndex(
			(it) => it.msg.id === msg.msg.id
		  );
		  const index = msg.msg.content.text.indexOf(">>end<<");
  
		  if (findIndex == -1) {
			this.oldSendMsgIndex = findIndex;
			this.msgList.push(msg);
			// uni.vibrateLong();
		  } else {
			if (index === -1) {
			  this.msgList.splice(findIndex, 1, msg);
			} else {
			  this.oldSendMsgIndex = 0;
			  this.appendContent = "";
			}
		  }
		}
		this.chatScrollTop();
	  },
	  chatScrollTop() {
		this.$nextTick(() => {
		  const query = uni.createSelectorQuery();
		  query.select(".dialogue-box").boundingClientRect();
		  query.select(".dialogue-box-content").boundingClientRect();
		  query.exec((res) => {
			const scrollViewHeight = res[0].height;
			const scrollContentHeight = res[1].height;
			if (scrollContentHeight > scrollViewHeight) {
			  const scrollTop = scrollContentHeight - scrollViewHeight;
			  this.scrollTop = scrollTop;
			}
		  });
		});
	  },
	  // 添加语音消息到列表
	  addVoiceMsg(msg) {
		this.msgList.push(msg);
		console.log(this.msgList, "测试发过去的音频");
	  },
	  // 添加图片消息到列表
	  addImgMsg(msg) {
		msg.msg.content = this.setPicSize(msg.msg.content);
		this.msgImgList.push(msg.msg.content.url);
		this.msgList.push(msg);
	  },
	  addRedEnvelopeMsg(msg) {
		this.msgList.push(msg);
	  },
	  // 添加系统文字消息到列表
	  addSystemTextMsg(msg) {
		this.msgList.push(msg);
	  },
	  // 添加系统红包消息到列表
	  addSystemRedEnvelopeMsg(msg) {
		this.msgList.push(msg);
	  },
  
	  sendSystemMsg(content, type) {
		let lastid = this.msgList[this.msgList.length - 1].msg.id;
		lastid++;
		let row = {
		  type: "system",
		  msg: { id: lastid, type: type, content: content },
		};
		this.screenMsg(row);
	  },
  
	  // 播放语音
	  playVoice(msg) {
		this.playMsgid = msg.id;
		this.AUDIO.src = msg.content.url;
		this.$nextTick(function () {
		  this.AUDIO.play();
		});
	  },
	  // 录音开始
	  voiceBegin(e) {
		if (e.touches.length > 1) {
		  return;
		}
		this.initPoint.Y = e.touches[0].clientY;
		this.initPoint.identifier = e.touches[0].identifier;
		this.RECORDER.start({ format: "wav" }); //录音开始,
	  },
	  //录音开始UI效果
	  recordBegin(e) {
		this.recording = true;
		this.voiceTis = "松开 结束";
		this.recordLength = 0;
		this.recordTimer = setInterval(() => {
		  this.recordLength++;
		}, 1000);
	  },
	  // 录音被打断
	  voiceCancel() {
		this.recording = false;
		this.voiceTis = "按住 说话";
		this.recordTis = "手指上滑 取消发送";
		this.willStop = true; //不发送录音
		this.RECORDER.stop(); //录音结束
	  },
	  // 录音中(判断是否触发上滑取消发送)
	  voiceIng(e) {
		if (!this.recording) {
		  return;
		}
		let touche = e.touches[0];
		//上滑一个导航栏的高度触发上滑取消发送
		if (this.initPoint.Y - touche.clientY >= uni.upx2px(100)) {
		  this.willStop = true;
		  this.recordTis = "松开手指 取消发送";
		} else {
		  this.willStop = false;
		  this.recordTis = "手指上滑 取消发送";
		}
	  },
	  // 结束录音
	  voiceEnd(e) {
		if (!this.recording) {
		  return;
		}
		this.recording = false;
		this.voiceTis = "按住 说话";
		this.recordTis = "手指上滑 取消发送";
		this.RECORDER.stop(); //录音结束
  
		console.log("拿到录音啦", e, e.tempFilePath);
	  },
	  //录音结束(回调文件)
	  recordEnd(e) {
		// debugger;
		console.log("拿语音url", e);
		clearInterval(this.recordTimer);
		if (!this.willStop) {
		  let msg = {
			length: 0,
			url: e.tempFilePath,
		  };
		  let min = parseInt(this.recordLength / 60);
		  let sec = this.recordLength % 60;
		  min = min < 10 ? "0" + min : min;
		  sec = sec < 10 ? "0" + sec : sec;
		  msg.length = min + ":" + sec;
		  console.log("e: " + JSON.stringify(e));
		  uni.uploadFile({
			url: "https://abc.gszczn.com:18586/terminal/lma/identifyVoice",
			filePath: e.tempFilePath,
			name: "voiceFile",
			success: (uploadRes) => {
			  console.log("上传成功", uploadRes);
			  // this.leftMsg(uploadRes.data, "text");
			  this.textMsg = uploadRes.data;
			  this.sendText();
			  // 在这里可以处理上传成功后的逻辑
			},
			fail(uploadErr) {
			  console.log("上传失败", uploadErr);
			  // 在这里可以处理上传失败后的逻辑
			},
		  });
		  // 将录音文件上传到后端
		} else {
		  console.log("取消发送录音");
		}
		this.willStop = false;
	  },
  
	  // 切换语音/文字输入
	  switchVoice() {
		this.hideDrawer();
		this.isVoice = this.isVoice ? false : true;
	  },
	  discard() {
		return;
	  },
	},
  };
  </script>
  <style lang="scss">
  @import "@/static/css/style.scss";
  </style>
  